#include "xja_sem.h"

// 创建信号灯集并初始化信号灯集 的函数（注意避免重复初始化的问题）
int xja_sem_init(int nums, const char *pathnema, char proj_id){
    // 生成key值
    key_t my_key = ftok(pathnema, proj_id);
    if(-1 == my_key)
        ERR_LOG("ftok error");
    // 创建或者获取共享内存
    int semid = semget(my_key, nums, IPC_CREAT|IPC_EXCL|0666);
    if(-1 == semid){
        if(EEXIST == errno){ // 已存在导致的错误
            if(-1 == (semid = semget(my_key, nums, IPC_CREAT|0666)))
                ERR_LOG("semget error");
            return semid;
        }else{ // 其他错误
            ERR_LOG("semget error");
        }
    }
    // 初始化信号灯集 0号灯置1  其他灯置0
    for(int i = 0; i < nums; i++){
        semctl(semid, i, SETVAL, !i);
    }
    return semid;
}

// P操作的函数
void xja_sem_P(int semid, int num){
    struct sembuf my_op = { // 用来做PV操作的结构体
        .sem_num = num,
        .sem_op = -1,
        .sem_flg = 0
    };
    if(-1 == semop(semid, &my_op, 1))
        ERR_LOG("semop error");
    // semop 支持一次操作多个灯 只要定义结构体数组 并填充好对每个灯的操作即可
    // 我们一般一次只操作一个灯
}

// V操作的函数
void xja_sem_V(int semid, int num){
    struct sembuf my_op = { // 用来做PV操作的结构体
        .sem_num = num,
        .sem_op = 1,
        .sem_flg = 0
    };
    if(-1 == semop(semid, &my_op, 1))
        ERR_LOG("semop error");
}

// 销毁信号灯集的函数
void xja_sem_destroy(int semid){
    if(-1 == semctl(semid, 0, IPC_RMID))
        ERR_LOG("semctl error");
}